package cn.kbyue.security.security;

import cn.kbyue.security.entity.KbPermission;
import cn.kbyue.security.entity.KbUser;
import cn.kbyue.security.entity.RolePermissions;
import cn.kbyue.security.service.RolePermissionService;
import cn.kbyue.security.service.UserService;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

/**
 * UserDetailsService 实现类
 *
 * @author xl
 * @date 2020/4/19 18:43
 */
@Service
public class DefinedUserDetailsServiceImpl implements UserDetailsService {

    @Resource
    private UserService userService;

    @Resource
    private RolePermissionService rolePermissionService;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        KbUser user = userService.findByName(username);

        String userId = Optional.ofNullable(user)
                .orElseThrow(() -> new AuthenticationServiceException("用户名或密码错误"))
                .getUserId();
        // 用户的角色-权限列表
        List<RolePermissions> userRolePermissions = rolePermissionService.getUserRolePermission(userId);
        Collection<GrantedAuthority> authorities = userRolePermissions.stream()
                .map(rolePermissions -> {
                    String code = rolePermissions.getRole().getCode();
                    List<String> permits = rolePermissions.getPermission().stream().map(KbPermission::getCode).collect(Collectors.toList());
                    return new DefinedGrantedAuthority(code, permits);
                }).collect(Collectors.toList());
        return new DefinedUserDetails(user, authorities);
    }
}
